package com.giec.autoble.service;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;

public class BleService extends Service {
    private static final String TAG = "BleService";
    private static final String SPP_UUID = "00000000-0000-1000-8000-00805F9B34FB";
    private static final String BLE_FILE = "ble_file";
    private static final String BLE_ADDRESS = "address";

    private BluetoothAdapter mBluetoothAdapter;
    private SharedPreferences mPreferences;

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            switch (action) {
                case BluetoothDevice.ACTION_PAIRING_REQUEST:
                    Log.d(TAG, "配对请求：");
                    Log.d(TAG, "onReceive: device.getName() = " + device.getName());
                    Log.d(TAG, "onReceive:  device.getAddress() = " + device.getAddress());
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    Log.d(TAG, "开始扫描...");
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    Log.d(TAG, "扫描结束.");
                    break;
                case BluetoothDevice.ACTION_FOUND:
//                    Log.d(TAG, "onReceive: 搜寻目标设备 = " + device.getName() + ", MAC = " + device.getAddress());
                    if (mLastDeviceAddress.equals(device.getAddress())) {
                        Log.d(TAG, "onReceive: 发现目标设备 = " + device.getName() + ", MAC = " + device.getAddress());
                        if (device.getBondState() == BluetoothDevice.BOND_NONE) {
                            Log.d(TAG, "onReceive: 目标设备未绑定");
                        } else if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
                            BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(mLastDeviceAddress);
                            remoteDevice.connectGatt(BleService.this, true, new BluetoothGattCallback() {
                                @Override
                                public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                                    super.onConnectionStateChange(gatt, status, newState);
                                    Log.d(TAG, "onConnectionStateChange: status = " + status + ", newState = " + newState);
                                }
                            });
                        }
                    }
                    break;
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                    switch (device.getBondState()) {
                        case BluetoothDevice.BOND_BONDING:
                            Log.d(TAG, "正在配对......");
                            break;
                        case BluetoothDevice.BOND_BONDED:
                            Log.d(TAG, "完成配对");
                            Log.d(TAG, "Device name: " + device.getName());
                            Log.d(TAG, "Device adderss: " + device.getAddress());
                            mPreferences.edit().putString(BLE_ADDRESS, device.getAddress()).apply();
                            break;
                        case BluetoothDevice.BOND_NONE:
                            Log.d(TAG, "取消配对：" + device.getName());
                            String bondedDevice = mPreferences.getString(BLE_ADDRESS, "");
                            if (bondedDevice != null && !TextUtils.isEmpty(bondedDevice)
                                    && bondedDevice.toUpperCase().equals(device.getAddress().toUpperCase())) {
                                mPreferences.edit().putString(BLE_ADDRESS, "").apply();
                                Log.d(TAG, "清空 : " + bondedDevice);
                            }
                            break;
                        default:
                            break;
                    }
                    break;
                case BluetoothDevice.ACTION_ACL_CONNECTED:
                    Log.d(TAG, "蓝牙设备:" + device.getName() + "已连接");
                    Log.d(TAG, "蓝牙设备:" + device.getAddress());
                    mPreferences.edit().putString(BLE_ADDRESS, device.getAddress()).apply();
                    break;
                case BluetoothDevice.ACTION_ACL_DISCONNECTED:
                    Log.d(TAG, "蓝牙设备:" + device.getName() + "已断开");
//                    mPreferences.edit().putString(BLE_ADDRESS, "").apply();
                    break;
                default:
                    Log.d(TAG, "onReceive: unkonw = " + action);
                    break;
            }
        }
    };
    private String mLastDeviceAddress;

    public BleService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mPreferences = getSharedPreferences(BLE_FILE, MODE_PRIVATE);
        initBLE();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        if (isConnected()) {
            String address = getConnectedDeviceAddress();
            Log.d(TAG, "onStartCommand: 蓝牙已连接: " + address);
            mPreferences.edit().putString(BLE_ADDRESS, address).apply();
        } else {
            startScanBLE();
//            connectLastDevice();
        }
        return START_STICKY;
    }

    private void startScanBLE() {
        Log.d(TAG, "startScanBLE: 蓝牙未连接");
        mLastDeviceAddress = mPreferences.getString(BLE_ADDRESS, "");
        Log.d(TAG, "保存的地址: " + mLastDeviceAddress);
        if (mLastDeviceAddress == null || TextUtils.isEmpty(mLastDeviceAddress)) {
            Log.d(TAG, "没有上一次的连接设备 ");
            return;
        }
        mBluetoothAdapter.startDiscovery();
    }

    /*
     * 未连接任何设备，尝试去连接上一次的设备(已经匹配过)
     * @Author: zgw
     * @Date:   2020/3/11 0011 12:20:17
     */
    private void connectLastDevice() {
        Log.d(TAG, "connectLastDevice: ");
        String lastDeviceAddress = mPreferences.getString(BLE_ADDRESS, "");
        Log.d(TAG, "保存的地址: " + lastDeviceAddress);
        if (lastDeviceAddress == null || TextUtils.isEmpty(lastDeviceAddress)) {
            Log.d(TAG, "没有上一次的连接设备 ");
            return;
        }

//        BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(lastDeviceAddress.toUpperCase());
//        Log.d(TAG, "remoteDevice.getName(): " + remoteDevice.getName());
//        Log.d(TAG, "remoteDevice.getAddress(): " + remoteDevice.getAddress());
//        remoteDevice.connectGatt(this, true, new BluetoothGattCallback() {
//            @Override
//            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
//                super.onConnectionStateChange(gatt, status, newState);
//                Log.d(TAG, "onConnectionStateChange: status = " + status + ", newState = " + newState);
//            }
//        });

        //寻找已经绑定的设备 zgw 2020/3/11 0011 12:22:09
        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
        if (bondedDevices.size() > 0) {
            for (Iterator<BluetoothDevice> it = bondedDevices.iterator(); it.hasNext(); ) {
                BluetoothDevice bluetoothDevice = it.next();
                Log.d(TAG, "Device name: " + bluetoothDevice.getName());
                Log.d(TAG, "Device address: " + bluetoothDevice.getAddress());
                if (lastDeviceAddress.toUpperCase().equals(bluetoothDevice.getAddress().toUpperCase())) {
                    Log.d(TAG, "connectLastDevice: 找到保存的蓝牙设备: " + bluetoothDevice.getName() + ", " + bluetoothDevice.getAddress());
                    if (!isRemoteConnected(bluetoothDevice)) {
                        bluetoothDevice.connectGatt(this, true, new BluetoothGattCallback() {
                            @Override
                            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                                super.onConnectionStateChange(gatt, status, newState);
                                Log.d(TAG, "onConnectionStateChange: status = " + status + ", newState = " + newState);
                            }
                        });
                        Log.d(TAG, "该蓝牙设备未连接：");
//                        connect(bluetoothDevice);
                    } else {
                        Log.d(TAG, "该蓝牙设备已连接: " + bluetoothDevice.getName());
                    }

                }
            }
        }
    }

    /*
     * 获取已连接的地址
     * @Author: zgw
     * @Date:   2020/3/11 0011 11:33:56
     */
    private String getConnectedDeviceAddress() {
        String address = "";
        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
        if (bondedDevices.size() > 0) {
            for (Iterator<BluetoothDevice> it = bondedDevices.iterator(); it.hasNext(); ) {
                BluetoothDevice bluetoothDevice = it.next();
                Log.d(TAG, "Device name: " + bluetoothDevice.getName());
                Log.d(TAG, "Device address: " + bluetoothDevice.getAddress());
                if (isRemoteConnected(bluetoothDevice)) {
                    Log.d(TAG, "已连接: " + bluetoothDevice.getName() + ", " + bluetoothDevice.getAddress());
                    address = bluetoothDevice.getAddress();
                    break;
                }
            }
        }
        return address;
    }

    /*
     * 判断远程设备的蓝牙是否已连接
     * @Author: zgw
     * @Date:   2020/3/11 0011 11:30:30
     */
    private boolean isRemoteConnected(BluetoothDevice device) {
        boolean isConnected = false;
        try {
            Method isConnectedMethod = BluetoothDevice.class.getMethod("isConnected", (Class[]) null);
            isConnectedMethod.setAccessible(true);
            isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isConnected;
    }

    /*
     * 判断当前设备的蓝牙是否已连接
     * @Author: zgw
     * @Date:   2020/3/11 0011 11:30:30
     */
    private boolean isConnected() {
        boolean isConnected = false;
        try {
            Method getConnectionStateMethod = BluetoothAdapter.class.getMethod("getConnectionState", (Class[]) null);
            getConnectionStateMethod.setAccessible(true);
            int state = (int) getConnectionStateMethod.invoke(mBluetoothAdapter, (Object[]) null);
            if (state == BluetoothAdapter.STATE_CONNECTED) {
                isConnected = true;
            } else {
                isConnected = false;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return isConnected;
    }

    private void initBLE() {
        Log.d(TAG, "initBLE: ");
        //初始化ble设配器
        if (mBluetoothAdapter == null) {
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        }
        //如果没打开蓝牙，不进行扫描操作，或请求打开蓝牙。
        if (!mBluetoothAdapter.isEnabled()) {
            Log.d(TAG, "蓝牙未打开");
            mBluetoothAdapter.enable();
            return;
        }
        // 注册广播接收器。
        // 接收蓝牙发现
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        registerReceiver(mReceiver, intentFilter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
        }
    }


    private void connect(BluetoothDevice btDev) {
        UUID uuid = UUID.fromString(SPP_UUID);
        BluetoothSocket btSocket;
        try {
            btSocket = btDev.createRfcommSocketToServiceRecord(uuid);
//            BluetoothSocket btSocket = btDev.createRfcommSocket(1);
            Log.d(TAG, "开始连接...");
            btSocket.connect();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Log.e(TAG, "开始连接......链接失败");
            e.printStackTrace();
        }
    }
}
